package edu.cs.networkmonitor.scanner;

import java.util.Vector;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import edu.cs.networkmonitor.devices.IPSource;

public class IPScanner extends BaseScanner {

	private String _lowRange;
	private String _highRange;
	public  Vector<IPSource> _ipList;

	public IPScanner(String low, String high) {
		_lowRange = low;
		_highRange = high;
		_ipList = new Vector<IPSource>();
	}

	@Override
	public void scan() {
		String currIp = _lowRange;
		ExecutorService executor = Executors.newFixedThreadPool(10);

		while (ipToInt(currIp) <= ipToInt(_highRange)) {
			final String ipNum =  currIp;
			Runnable ipTask = new Runnable() {
				public void run() {
					IPSource ip = new IPSource(ipNum);
					if(ip.connect()){
						_ipList.add(ip);
					}
				}
			};
			executor.execute(ipTask);
			currIp = getNextIPV4Address(currIp);
		}

	    executor.shutdown();
	    // Wait until all threads are finish
	    while (!executor.isTerminated()) {

	    }
	    System.out.println("Finished all threads");
	}

	public static long ipToInt(String addr) {
		String[] addrArray = addr.split("\\.");
		long num = 0;
		for (int i = 0; i < addrArray.length; i++) {
			int power = 3 - i;
			num += ((Integer.parseInt(addrArray[i]) % 256 * Math
					.pow(256, power)));
		}
		return num;
	}

	public static String intToIp(int i) {
		return ((i >> 24) & 0xFF) + "." + ((i >> 16) & 0xFF) + "."
				+ ((i >> 8) & 0xFF) + "." + (i & 0xFF);
	}

	public static String getNextIPV4Address(String ip) {
		String[] nums = ip.split("\\.");
		int i = (Integer.parseInt(nums[0]) << 24
				| Integer.parseInt(nums[2]) << 8
				| Integer.parseInt(nums[1]) << 16 | Integer.parseInt(nums[3])) + 1;

		// If you wish to skip over .255 addresses.
		if ((byte) i == -1)
			i++;

		return String.format("%d.%d.%d.%d", i >>> 24 & 0xFF, i >> 16 & 0xFF,
				i >> 8 & 0xFF, i >> 0 & 0xFF);
	}

    public Object[][] getColumnData() {
        Object[][] data = new Object[_ipList.size()][3];
        for (int i = 0; i < _ipList.size(); i++) {
            data[i][0] = _ipList.get(i).getSourceName();
            data[i][1] = _ipList.get(i).getDeviceDescription();
        }
        return data;
    }

	public Vector<IPSource> getSources() {
		return _ipList;
	}

}
